/*-------------------------------------------------------------------------
 *
 * hsearch.h
 *	  导出的定义用于utils/hash/dynahash.c；请参阅其中的注释
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/utils/hsearch.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef HSEARCH_H
#define HSEARCH_H


/*
 * 哈希函数必须具有此签名。
 */
typedef uint32 (*HashValueFunc) (const void *key, Size keysize);

/*
 * 键比较函数必须具有此签名。比较函数
 * 匹配时返回零，不匹配时返回非零。 （比较函数的
 * 定义旨在允许 memcmp() 和 strncmp() 被直接用作键比较函数。）
 */
typedef int (*HashCompareFunc) (const void *key1, const void *key2,
								Size keysize);

/*
 * 键复制函数必须具有此签名。返回值不
 * 被使用。 （定义设置为允许 memcpy() 和 strlcpy() 被
 * 直接使用。）
 */
typedef void *(*HashCopyFunc) (void *dest, const void *src, Size keysize);

/*
 * 哈希表的空间分配函数---设计与 malloc() 匹配。
 * 注意：没有释放函数 API；无法销毁哈希表，除非你
 * 使用默认分配器。
 */
typedef void *(*HashAllocFunc) (Size request);

/*
 * HASHELEMENT 是哈希表条目的私有部分。调用者的数据
 * 紧随 HASHELEMENT 结构后面（在 MAXALIGN 边界上）。哈希键
 * 应该位于调用者哈希条目数据结构的开始位置。
 */
typedef struct HASHELEMENT
{
	struct HASHELEMENT *link;	/* 链接到同一桶中的下一个条目 */
	uint32		hashvalue;		/* 此条目的哈希函数结果 */
} HASHELEMENT;

/* 哈希表头结构是一个在 dynahash.c 中仅为私有类型 */
typedef struct HASHHDR HASHHDR;

/* 哈希表控制结构是一个在 dynahash.c 中仅为私有类型 */
typedef struct HTAB HTAB;

/* hash_create 的参数数据结构 */
/* 仅需设置 hash_flags 指示的那些字段 */
typedef struct HASHCTL
{
	/* 如果设置了 HASH_PARTITION 标志，则使用： */
	long		num_partitions; /* 分区数量（必须是 2 的幂） */
	/* 如果设置了 HASH_SEGMENT 标志，则使用： */
	long		ssize;			/* 段大小 */
	/* 如果设置了 HASH_DIRSIZE 标志，则使用： */
	long		dsize;			/* （初始）目录大小 */
	long		max_dsize;		/* 如果目录大小有限，则限制为 dsize */
	/* 如果设置了 HASH_ELEM 标志（现在是必须的），则使用： */
	Size		keysize;		/* 哈希键的字节长度 */
	Size		entrysize;		/* 用户元素的总大小（以字节为单位） */
	/* 如果设置了 HASH_FUNCTION 标志，则使用： */
	HashValueFunc hash;			/* 哈希函数 */
	/* 如果设置了 HASH_COMPARE 标志，则使用： */
	HashCompareFunc match;		/* 键比较函数 */
	/* 如果设置了 HASH_KEYCOPY 标志，则使用： */
	HashCopyFunc keycopy;		/* 键复制函数 */
	/* 如果设置了 HASH_ALLOC 标志，则使用： */
	HashAllocFunc alloc;		/* 内存分配器 */
	/* 如果设置了 HASH_CONTEXT 标志，则使用： */
	MemoryContext hcxt;			/* 用于分配的内存上下文 */
	/* 如果设置了 HASH_SHARED_MEM 标志，则使用： */
	HASHHDR    *hctl;			/* 共享内存中头部的位置 */
} HASHCTL;

/* hash_create 的标志位；大多数指示提供了哪些参数 */
#define HASH_PARTITION	0x0001	/* 哈希表与分区锁定一起使用 */
#define HASH_SEGMENT	0x0002	/* 设置段大小 */
#define HASH_DIRSIZE	0x0004	/* 设置目录大小（初始和最大） */
#define HASH_ELEM		0x0008	/* 设置键大小和条目大小（现在是必须的！） */
#define HASH_STRINGS	0x0010	/* 选择字符串键的支持函数 */
#define HASH_BLOBS		0x0020	/* 选择二进制键的支持函数 */
#define HASH_FUNCTION	0x0040	/* 设置用户定义的哈希函数 */
#define HASH_COMPARE	0x0080	/* 设置用户定义的比较函数 */
#define HASH_KEYCOPY	0x0100	/* 设置用户定义的键拷贝函数 */
#define HASH_ALLOC		0x0200	/* 设置内存分配器 */
#define HASH_CONTEXT	0x0400	/* 设置内存分配上下文 */
#define HASH_SHARED_MEM 0x0800	/* 哈希表在共享内存中 */
#define HASH_ATTACH		0x1000	/* 不初始化 hctl */
#define HASH_FIXED_SIZE 0x2000	/* 初始大小是硬限制 */

/* max_dsize 值指示可扩展目录 */
#define NO_MAX_DSIZE			(-1)

/* hash_search 操作 */
typedef enum
{
	HASH_FIND,
	HASH_ENTER,
	HASH_REMOVE,
	HASH_ENTER_NULL
} HASHACTION;

/* hash_seq 状态（调用者应将其视为不透明类型） */
typedef struct
{
	HTAB	   *hashp;
	uint32		curBucket;		/* 当前桶的索引 */
	HASHELEMENT *curEntry;		/* 当前桶中的条目 */
} HASH_SEQ_STATUS;

/*
 * dynahash.c 中函数的原型
 */
extern HTAB *hash_create(const char *tabname, long nelem,
						 const HASHCTL *info, int flags);
extern void hash_destroy(HTAB *hashp);
extern void hash_stats(const char *where, HTAB *hashp);
extern void *hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action,
						 bool *foundPtr);
extern uint32 get_hash_value(HTAB *hashp, const void *keyPtr);
extern void *hash_search_with_hash_value(HTAB *hashp, const void *keyPtr,
										 uint32 hashvalue, HASHACTION action,
										 bool *foundPtr);
extern bool hash_update_hash_key(HTAB *hashp, void *existingEntry,
								 const void *newKeyPtr);
extern long hash_get_num_entries(HTAB *hashp);
extern void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp);
extern void *hash_seq_search(HASH_SEQ_STATUS *status);
extern void hash_seq_term(HASH_SEQ_STATUS *status);
extern void hash_freeze(HTAB *hashp);
extern Size hash_estimate_size(long num_entries, Size entrysize);
extern long hash_select_dirsize(long num_entries);
extern Size hash_get_shared_size(HASHCTL *info, int flags);
extern void AtEOXact_HashTables(bool isCommit);
extern void AtEOSubXact_HashTables(bool isCommit, int nestDepth);

#endif							/* HSEARCH_H */
